#pragma once
#include <iostream>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <cstring>
#include "log.hpp"
using namespace std;
class Sock
{
public:
    static int Socket()
    {
        int fd = socket(AF_INET, SOCK_STREAM, 0);
        if (fd == -1)
        {
            logMessage(ERROR, "socket fail");
            exit(SOCK_ERR);
        }
        logMessage(NORMAL, "socket success");
        int opt = 1;
        setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &opt, sizeof(opt));
        return fd;
    }
    static void Bind(int fd, uint16_t port)
    {
        struct sockaddr_in addr;
        bzero(&addr, sizeof(addr));
        addr.sin_family = AF_INET;
        addr.sin_addr.s_addr = INADDR_ANY;
        addr.sin_port = htons(port);
        int ret = bind(fd, (struct sockaddr *)&addr, sizeof(addr));
        if (ret == -1)
        {
            logMessage(ERROR, "bind fail");
            exit(BIND_ERR);
        }
        logMessage(NORMAL, "bind success");
    }
    static void Listen(int fd)
    {
        int ret = listen(fd, 5);
        if (ret == -1)
        {
            logMessage(ERROR, "listen fail");
            exit(LISTEN_ERR);
        }
        logMessage(NORMAL, "listen success");
    }
    static int Accept(int listenfd, string &ip, uint16_t &port)
    {
        struct sockaddr_in addr;
        socklen_t len = sizeof(addr);
        int fd = accept(listenfd, (struct sockaddr *)&addr, &len);
        if (fd == -1)
        {
            logMessage(ERROR, "accept fail");
            exit(ACCEPT_ERR);
        }
        ip = inet_ntoa(addr.sin_addr);
        port = ntohs(addr.sin_port);
        logMessage(NORMAL, "accept success [%d][%s][%d]", fd, ip.c_str(), port);
        return fd;
    }
};